import argparse
import time

from bitcoin_client import BitcoinClient
from database import Database
from converter import Converter
from error import Error
from progress import Progress
from utils import load_config, get_password_regex

# 起止索引
parser = argparse.ArgumentParser("Process some integers.")
parser.add_argument('start_index', type=int)
parser.add_argument('end_index', type=int)
args = parser.parse_args()
START_INDEX = args.start_index
END_INDEX = args.end_index

# START_INDEX = 0
# END_INDEX = 1000

# 配置
config = load_config()
DATABASE_PATH = f"db_{START_INDEX}_{END_INDEX}.db"
RECIPIENT_ADDRESS = config['RECIPIENT_ADDRESS']
AMOUNT = config['AMOUNT']
LOG_STEP = config['LOG_STEP']
AVG_BASE_TIME_NUM = config['AVG_BASE_TIME_NUM']

# 转换器
converter = Converter()

# 数据库
db = Database(DATABASE_PATH, converter)
db.create_table(START_INDEX, END_INDEX)

# 当前进度记录
record = db.query_record(START_INDEX, END_INDEX)

# 已找到密码，退出
if record["hit_index"] != -1:
    print(f"密码已破解：{record['hit_convert']}")
    exit()

# 已遍历完所有密码，退出
if record["current_index"] == END_INDEX - 1:
    print("该范围的密码均已尝试，无可用密码。")
    exit()

# 密码正则表达式
password_regex = get_password_regex(config['LETTERS_TYPE'])

# 连接钱包
wallet = BitcoinClient(config['RPC_HOST'], config['RPC_PORT'], config['RPC_USER'], config['RPC_PASSWORD'])

# 起始索引
start_index = START_INDEX
if record["current_index"] != -1:
    start_index = record["current_index"]

# 进度条控制器
progress = Progress(END_INDEX - START_INDEX, LOG_STEP, AVG_BASE_TIME_NUM)
if record["current_index"] != -1:
    progress.update(num=record["current_index"] - START_INDEX)

for i in range(start_index, END_INDEX):
    password = converter.to_string(i)

    # 跳过不在密码范围内的密码
    allow = False
    for regex in password_regex:
        if regex.match(password):
            allow = True
            break
    if allow is False:
        progress.update(message=f"密码：`{password}`。跳过，不在密码范围内。")
        continue

    transaction_id = None

    while True:
        try:
            # 进行转账
            transaction_id = wallet.transfer(password, RECIPIENT_ADDRESS, AMOUNT)
        except Error as e:
            # 密码错误，跳过
            if e.code == -14:
                db.update_record(START_INDEX, END_INDEX, current=(i, password))
                progress.update(message=f"密码：`{password}`。Error：{e.message}")
                break
            # 与钱包连接失败，重新连接
            elif e.code in [10053, 10053002, -28, 10061]:
                while True:
                    try:
                        wallet = BitcoinClient(config['RPC_HOST'], config['RPC_PORT'], config['RPC_USER'],
                                               config['RPC_PASSWORD'])
                    except Error as e:
                        progress.set_message(f"连接钱包失败：{e.message}。5秒后尝试重新连接...")
                        time.sleep(5)
                    break
            # 其他错误，记录并跳过
            else:
                db.add_failed_record(i, password, e.type, e.code, e.message)
                db.update_record(START_INDEX, END_INDEX, current=(i, password))
                progress.update(message=f"密码：`{password}`。Error：{e.message}")
                break

    if transaction_id is not None:
        # 转账成功
        db.update_record(START_INDEX, END_INDEX, current=(i, password), hit=(i, password))
        progress.update(message=f"密码：`{password}`。交易ID：{transaction_id}")
        break
